
from dao import create_db,remember_dao,user_dao
from utils import gen_mds,gen_random_string
from x_com import xport_core
from x_com import source_api
#import sqlalchemy
from sqlalchemy.ext.asyncio import create_asyns_engine
from databases import Database
logger = xport_core.getLogger()

class UserService:
    # 设置 sqlite 的连接方式和存放地址
    DATABASE_URL = "sqlite+aiosqlite:///./user.db"
    database = Database(DATABASE_URL)
    engine = create_async_engine(DATABASE_URL, echo=True)
    # 当前登录用户的id
    user_id = 0
    async def init_db(self):
        # 初始化数据库配置
        # 创建数据库连接
        await self.database.connect()
        # 创建数据库
        await create_db()

    # 服务加载时，调用出事函数，用于执行初始化操作
    async def on_init(self):
        # 初始化数据库
        await self.init_db()

    # 服务卸载时，调用函数
    async def on_finalize(self):
        pass

    # AddUser
    # 添加用户
    async def add_user(self, ctx: xport_core.Context,  param: source_api.UserInfo):
        # 开启事务，因为需要修改数据库，因此要开启事务
        async with self.engine.begin() as conn:
            # 根据用户名查找用户，判断用户名是否已经存在
            user = await user_dao.find_by_name(conn, param.username)
            if user is not None:
                raise Exception(f"用户：{param.username} 已经存在")
            # 生成随机字符串
            salt = gen_random_string()
            # 生成密码的 md5 值
            md5 = gen_md5(param.password)
            # 加上随机字符串后，再生成 md5，这样设计是防止密码被暴力破解
            md5_with_salt = gen_md5(md5 + salt)
            # 存入数据库
            await user_dao.add_user(conn, param.username, md5_with_salt, salt)

    # Login
    # 登录 
    async def login(self, ctx: xport_core.Context,  param: source_api.UserInfo):
        # 开始事务，因为登陆时，要写入是否要记住用户名密码，设置修改数据库
        async with self.engine.begin() as conn:
            user_model = await user_dao.find_by_name(conn, param.username)
            if user_model is None:
                raise Exception(f"用户：{param.username} 不存在！")
            md5 = gen_md5(param.password)
            md5 = gen_md5(md5 + user_model.salt)
            if md5.lower() != user_model.password:
                raise Exception("密码错误！")
            self.user_id = user_model.id
            # 判断上次用户是否记住密码
            remember = await remember_dao.find_by_id(conn)
            is_remember = remember is not None
            if param.remember:
                if is_remember:
                    # 上一次登录记住密码，本次也记住密码，则更新
                    await remember_dao.update(conn, param.username, param.password)
                else:
                     # 上次没记住密码，本次记住密码，则插入
                    await remember_dao.insert(conn, param.username, param.password)
            else:
                if is_remember:
                    # 本次不记住密码，清空
                    await remember_dao.update(conn, "", "")
    # IsLogin
    # 用户是否登录
    async def is_login(self, ctx: xport_core.Context) -> source_api.BoolResponse:
        resp = source_api.BoolResponse()
        resp.value = self.user_id != 0
        return resp

    # GetRememberAccount
    # 获取记住的密码
    async def get_remember_account(self, ctx: xport_core.Context) -> source_api.UserInfo:
        async with self.engine.connect() as conn:
          resp = source_api.UserInfo()
          # 返回上次记住的密码
          remember = await remember_dao.find_by_id(conn)
          if remember is not None:
              resp.username = remember.username
              resp.password = remember.password
          return resp
